package com.sea.base.anim

import android.animation.Animator
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.animation.ValueAnimator.*
import android.annotation.SuppressLint
import android.view.View
import androidx.vectordrawable.graphics.drawable.ArgbEvaluator
import com.sea.base.R
import com.sea.base.ext.view.doOnDetachCanCancel

/**
 * ValueAnimator的优化版
 * 1.增加泛型，对值可直接获取，无需强转
 * 2.增加[start]，自动detach，自动取消之前的动画
 *
 */
open class MyValueAnimator<T> protected constructor() : ValueAnimator() {
    private var onAnimEndForViewListener: AnimatorListener? = null

    companion object {
        /**
         * @param values 2个及以上
         */
        @JvmStatic
        fun ofInt(vararg values: Int) = MyValueAnimator<Int>().apply { setIntValues(*values) }

        @JvmStatic
        fun ofInt(target: Any, propertyName: String, vararg values: Int) = ObjectAnimator.ofInt(target, propertyName, *values)

        @JvmStatic
        fun ofFloat(vararg values: Float) = MyValueAnimator<Float>().apply { setFloatValues(*values) }

        @JvmStatic
        fun ofFloat(target: Any, propertyName: String, vararg values: Float) = ObjectAnimator.ofFloat(target, propertyName, *values)

        @JvmStatic
        @SuppressLint("RestrictedApi")//androidx限制group内使用，可直接忽略
        fun ofArgb(vararg values: Int) = MyValueAnimator<Int>().apply {
            setIntValues(*values)
            setEvaluator(ArgbEvaluator.getInstance())
        }

        @JvmStatic
        fun ofArgb(target: Any, propertyName: String, vararg values: Int) = ObjectAnimator.ofArgb(target, propertyName, *values)
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // Animator方法实现
    /////////////////////////////////////////////////////////////////////////////////////////////////
    /**
     * 1.和view一一对应，animator绑多个view或view绑多个animator都会取消前者
     * 2.view detach时会自动取消
     */
    fun start(attachView: View) {
        //取消上一次
        AnimUtil.cancelAnim(attachView)
        removeViewListener()

        //添加新的
        attachView.setTag(R.id.tag_anim, this)
        val attachListener = attachView.doOnDetachCanCancel { cancel() }
        onAnimEndForViewListener = addListener {
            attachView.removeOnAttachStateChangeListener(attachListener)
            removeViewListener()
        }

        start()
    }

    private fun removeViewListener() {
        removeListener(onAnimEndForViewListener)
        onAnimEndForViewListener = null
    }

    override fun cancel() {
        super.cancel()
        removeViewListener()
    }

    /**
     * @param onEnd cancel时也会被立即调用
     */
    inline fun addListener(
        crossinline onStart: (MyValueAnimator<T>.() -> Unit) = {},
        crossinline onCancel: (MyValueAnimator<T>.() -> Unit) = {},
        crossinline onRepeat: (MyValueAnimator<T>.() -> Unit) = {},
        crossinline onEnd: (MyValueAnimator<T>.() -> Unit) = {}
    ): AnimatorListener {
        val obj = object : AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                onStart.invoke(this@MyValueAnimator)
            }

            override fun onAnimationEnd(animation: Animator) {
                onEnd.invoke(this@MyValueAnimator)
            }

            override fun onAnimationCancel(animation: Animator) {
                onCancel.invoke(this@MyValueAnimator)
            }

            override fun onAnimationRepeat(animation: Animator) {
                onRepeat.invoke(this@MyValueAnimator)
            }

        }
        addListener(obj)
        return obj
    }

    /**
     * 根据泛型返回的值
     */
    @Suppress("UNCHECKED_CAST")
    val animatedValueT: T
        get() = animatedValue as T

    inline fun addUpdateListener(crossinline upListener: MyValueAnimator<T>.(value: T) -> Unit): AnimatorUpdateListener {
        val l = AnimatorUpdateListener { this.upListener(animatedValueT) }
        addUpdateListener(l)
        return l
    }
}